package com.bwton.msx.ccb.ui.setting.adapter;

import android.content.Context;
import android.graphics.Color;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;


import com.bwton.msx.ccb.R;
import com.bwton.msx.ccb.utils.MotionUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MotionSequenceRecyclerAdapter extends RecyclerView.Adapter<MotionSequenceRecyclerAdapter.ViewHolder>
        implements ItemTouchHelperAdapter {

    private final List<Integer> mSequence;
    private int mPrefixImageResource = R.drawable.ic_remove;
    private int mLastOneImageResource = R.drawable.ic_delete_deny;
    private int mSuffixImageResource = R.drawable.ic_more;
    private boolean mPrefixImageEnable = true;
    private boolean mSuffixImageEnable = true;
    private boolean mLastOneEnable = true;
    private RecyclerOperationListener mOperationListener;
    private Context mContext;

    /**
     * Constructor.
     *
     * @param context  context.
     * @param listener listener.
     */
    public MotionSequenceRecyclerAdapter(final Context context, final RecyclerOperationListener listener) {
        this.mContext = context;
        this.mSequence = new ArrayList<>();
        this.mOperationListener = listener;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.recycler_item_modifiable_motion, parent, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        final int itemIndex = position;

        holder.mCharacterText.setText(
                this.mContext.getResources().getString(MotionUtil.getMotionNameResID(this.mSequence.get(position))));

        holder.mPrefixImage.setVisibility(this.mPrefixImageEnable ? View.VISIBLE : View.GONE);
        holder.mPrefixImage.setImageResource(
                this.mSequence.size() != 1 ? this.mPrefixImageResource : this.mLastOneImageResource);

        holder.mPrefixImage.setEnabled(this.mLastOneEnable ? true : this.mSequence.size() != 1);
        holder.mPrefixImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mOperationListener.onItemDeleted(itemIndex);
            }
        });

        holder.mSuffixImage.setVisibility(
                this.mSuffixImageEnable ? (this.mSequence.size() != 1 ? View.VISIBLE : View.GONE) : View.GONE);
        holder.mSuffixImage.setImageResource(this.mSuffixImageResource);
    }

    @Override
    public int getItemCount() {
        return this.mSequence.size();
    }

    public void setPrefixImageEnable(final boolean enable) {
        this.mPrefixImageEnable = enable;
    }

    public void setSuffixImageEnable(final boolean enable) {
        this.mSuffixImageEnable = enable;
    }

    public void setPrefixImageResource(final int prefixImageResource) {
        this.mPrefixImageResource = prefixImageResource;
    }

    public void setSuffixImageResource(final int suffixImageResource) {
        this.mSuffixImageResource = suffixImageResource;
    }

    public void setLastOneImageResource(final int specialImageResource) {
        this.mLastOneImageResource = specialImageResource;
    }

    public void setLastOneEnable(final boolean enable) {
        this.mLastOneEnable = enable;
    }

    /**
     * Add motion to sequence.
     *
     * @param motion motion to add.
     */
    public void addMotion(final int motion) {
        this.mSequence.add(motion);
        this.notifyDataSetChanged();
    }

    /**
     * Update all adapter data.
     *
     * @param sequence data of this adapter.
     */
    public void removeAndAddSequence(final List<Integer> sequence) {
        this.mSequence.clear();

        if (sequence != null) {
            this.mSequence.addAll(sequence);
        }

        this.notifyDataSetChanged();
    }

    /**
     * Update motion of sequence.
     *
     * @param position position of motion to be update.
     * @param motion   new motion.
     */
    public void updateMotion(final int position, final int motion) {
        if (position >= this.mSequence.size()
                || MotionUtil.getMotionNameResID(motion) < 0
                || this.mSequence.get(position) == motion) {
            return;
        }

        this.mSequence.set(position, motion);

        this.notifyDataSetChanged();
    }

    /**
     * Delete motion from sequence.
     *
     * @param position position of motion to delete.
     */
    public void deleteMotion(final int position) {
        if (position >= this.mSequence.size()) {
            return;
        }

        this.mSequence.remove(position);
        this.notifyDataSetChanged();
    }

    @Override
    public void onItemMove(RecyclerView.ViewHolder source, int fromPosition, int toPosition) {
        Collections.swap(this.mSequence, fromPosition, toPosition);

        notifyItemMoved(fromPosition, toPosition);

        if (this.mOperationListener != null) {
            this.mOperationListener.onDataReorder(this.mSequence);
        }

        onItemClear(source);
    }

    @Override
    public void onItemSelect(RecyclerView.ViewHolder source) {
        source.itemView.setBackgroundColor(Color.LTGRAY);
    }

    @Override
    public void onItemClear(RecyclerView.ViewHolder source) {
        source.itemView.setBackgroundColor(Color.TRANSPARENT);
    }

    public interface RecyclerOperationListener {
        void onItemDeleted(final int index);

        void onDataReorder(final List<Integer> data);
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        final View mView;
        final AppCompatImageView mPrefixImage;
        final TextView mCharacterText;
        final AppCompatImageView mSuffixImage;

        ViewHolder(final View view) {
            super(view);
            this.mView = view;
            this.mPrefixImage = this.mView.findViewById(R.id.img_pre_flag);
            this.mCharacterText = this.mView.findViewById(R.id.txt_character);
            this.mSuffixImage = this.mView.findViewById(R.id.img_suffix_flag);
        }
    }

    public class MotionRecyclerViewTouchHelperCallback extends ItemTouchHelper.Callback {

        private ItemTouchHelperAdapter mAdapter;

        public MotionRecyclerViewTouchHelperCallback(ItemTouchHelperAdapter adapter) {
            this.mAdapter = adapter;
        }

        @Override
        public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
            return makeMovementFlags(dragFlags, 0);
        }

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
            // Do nothing.
        }

        @Override
        public boolean isLongPressDragEnabled() {
            return true;
        }

        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
                              RecyclerView.ViewHolder target) {
            this.mAdapter.onItemMove(viewHolder, viewHolder.getAdapterPosition(), target.getAdapterPosition());
            return true;
        }

        @Override
        public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
            if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
                this.mAdapter.onItemSelect(viewHolder);
            }
            super.onSelectedChanged(viewHolder, actionState);
        }

        @Override
        public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            super.clearView(recyclerView, viewHolder);
            if (!recyclerView.isComputingLayout()) {
                this.mAdapter.onItemClear(viewHolder);
            }
        }
    }
}
